import org.apache.log4j.Logger;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Created by patrick on 9/7/2017.
 */
public abstract class TreeNode<T extends TreeNode> implements Comparable<T> {

    private static Logger logger = Logger.getLogger(Comparable.class);

    private String id;
    private String parentId;
    private String nodeName;
    private int columnsCount;
    private int rowsCount;
    private int level;
    private int orderNo;
    private List<T> childList;

    private TreeNode() {
    }

    public TreeNode(String id) {
        this.id = id;
        this.rowsCount = 1;
    }

    /**
     * 获取当前节点所有子孙节点集合
     *
     * @return
     */
    public List<T> getAllChildList() {
        List<T> allChildList = new ArrayList<T>();
        if (this.hasChild()) {
            return allChildList;
        } else {
            for (T child : this.childList) {
                allChildList.add(child);
                if (child.hasChild()) {
                    allChildList.addAll(child.getAllChildList());
                }
            }
        }
        return allChildList;
    }

    /**
     * 添加子节点
     *
     * @param treeNode
     */
    public void addChild(T treeNode) {
        if ((this.id == null && treeNode.getParentId() != null) || (this.id != null && !this.id.equals(treeNode.getParentId())))
            return;
        initChildList();
        if (treeNode.getLevel() == 0) {
            treeNode.setLevel(this.level + 1);
        }

        this.childList.add(treeNode);
        Collections.sort(this.childList);
    }


    /**
     * 获取当前节点所占行数
     *
     * @return
     */
    public int getAllChildRowsCount() {
        int count = 0;
        if (this.hasChild()) {
            for (T child : this.childList) {
                if (child.hasChild())
                    count += child.getAllChildRowsCount();
                else
                    count += child.getRowsCount();
            }
        } else {
            count++;
        }

        return count;
    }

    /**
     * 根据父ID添加节点到树
     *
     * @param node
     * @return
     */
    public boolean addNode(T node) {
        String pId = node.getParentId();
        if (this.id.equals(pId)) {
            this.addChild(node);
            return true;
        }
        this.initChildList();
        for (T child : this.childList) {
            boolean flag = child.addNode(node);
            if (flag)
                return true;
        }

        return false;
    }

//    public abstract T findNodeById(String id);

    /**
     * 生成一行方法
     *
     * @return
     */
    public String genTableRow() {
        StringBuffer sb = new StringBuffer();
        sb.append("<td");
        if (this.columnsCount > 1){
            sb.append(" colspan=\"");
            sb.append(this.columnsCount);
            sb.append("\" ");
        }
        if (this.rowsCount > 1){
            sb.append(" rowspan=\"");
            sb.append(this.rowsCount);
            sb.append("\" ");
        }
        sb.append(">");
        sb.append(this.nodeName);
        sb.append("</td>");

        return sb.toString();
    }


    /**
     * 是否有子节点
     *
     * @return
     */
    public boolean hasChild() {
        return this.childList != null;
    }


    public void initChildList() {
        if (!this.hasChild())
            this.childList = new ArrayList<T>();
    }


    public int compareTo(T o) {
        return this.orderNo - o.getOrderNo();
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getParentId() {
        return parentId;
    }

    public void setParentId(String parentId) {
        this.parentId = parentId;
    }

    public String getNodeName() {
        return nodeName;
    }

    public void setNodeName(String nodeName) {
        this.nodeName = nodeName;
    }

    public int getColumnsCount() {
        return columnsCount;
    }

    public void setColumnsCount(int columnsCount) {
        this.columnsCount = columnsCount;
    }

    public int getRowsCount() {
        return rowsCount;
    }

    public void setRowsCount(int rowsCount) {
        this.rowsCount = rowsCount;
    }

    public int getLevel() {
        return level;
    }

    public void setLevel(int level) {
        this.level = level;
    }

    public int getOrderNo() {
        return orderNo;
    }

    public void setOrderNo(int orderNo) {
        this.orderNo = orderNo;
    }

    public List<T> getChildList() {
        return childList;
    }

    public void setChildList(List<T> childList) {
        this.childList = childList;
    }

}
